#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <uv.h>

#define CAT_BUF_SIZE 8192
#define MAX_BUFFERS 2

struct uvcat_context {
    uv_loop_t *loop;
    uv_fs_t open_req;
    uv_fs_t read_req;
    uv_fs_t write_req;
    uv_fs_t close_req;
    uv_buf_t buffers[MAX_BUFFERS];
    int current_buffer;
    int file_fd;
    int is_closing;
    int bytes_read;
    int bytes_written;
};

static struct uvcat_context *g_ctx = NULL;

void signal_handler(int sig) {
    if (g_ctx && !g_ctx->is_closing) {
        fprintf(stderr, "\nReceived signal %d, closing gracefully...\n", sig);
        g_ctx->is_closing = 1;
        if (g_ctx->file_fd >= 0) {
            uv_fs_close(g_ctx->loop, &g_ctx->close_req, g_ctx->file_fd, NULL);
        }
    }
}

void uvcat_context_init(struct uvcat_context *ctx, uv_loop_t *loop) {
    ctx->loop = loop;
    ctx->file_fd = -1;
    ctx->is_closing = 0;
    ctx->current_buffer = 0;
    ctx->bytes_read = 0;
    ctx->bytes_written = 0;
    
    // 设置请求的数据指针
    ctx->open_req.data = ctx;
    ctx->read_req.data = ctx;
    ctx->write_req.data = ctx;
    ctx->close_req.data = ctx;
    
    // 分配多个缓冲区
    for (int i = 0; i < MAX_BUFFERS; i++) {
        char *buffer = malloc(CAT_BUF_SIZE);
        if (!buffer) {
            fprintf(stderr, "Failed to allocate buffer %d\n", i);
            exit(1);
        }
        ctx->buffers[i] = uv_buf_init(buffer, CAT_BUF_SIZE);
    }
}

void uvcat_context_cleanup(struct uvcat_context *ctx) {
    if (!ctx) {
        return;
    }
    
    // 释放缓冲区
    for (int i = 0; i < MAX_BUFFERS; i++) {
        if (ctx->buffers[i].base) {
            free(ctx->buffers[i].base);
            ctx->buffers[i].base = NULL;
            ctx->buffers[i].len = 0;
        }
    }
    
    // 清理文件系统请求
    uv_fs_req_cleanup(&ctx->open_req);
    uv_fs_req_cleanup(&ctx->read_req);
    uv_fs_req_cleanup(&ctx->write_req);
    uv_fs_req_cleanup(&ctx->close_req);
}

static void close_cb(uv_fs_t *req) {
    struct uvcat_context *ctx = req->data;
    assert(req == &ctx->close_req);
    
    if (req->result == 0) {
        fprintf(stderr, "File closed successfully. Read: %d bytes, Written: %d bytes\n", 
                ctx->bytes_read, ctx->bytes_written);
    } else {
        fprintf(stderr, "Error closing file: %s\n", uv_strerror(req->result));
    }
    
    // 停止事件循环
    uv_stop(ctx->loop);
}

static void read_cb(uv_fs_t *req);
static void write_cb(uv_fs_t *req) {
    struct uvcat_context *ctx = req->data;
    assert(req == &ctx->write_req);
    
    if (req->result >= 0) {
        ctx->bytes_written += req->result;
        
        // 如果正在关闭，不再继续读取
        if (ctx->is_closing) {
            uv_fs_close(ctx->loop, &ctx->close_req, ctx->file_fd, close_cb);
            return;
        }
        
        // 切换到下一个缓冲区并继续读取
        ctx->current_buffer = (ctx->current_buffer + 1) % MAX_BUFFERS;
        uv_fs_read(ctx->loop, &ctx->read_req, ctx->file_fd, 
                   &ctx->buffers[ctx->current_buffer], 1, -1, read_cb);
    } else {
        fprintf(stderr, "Error writing to stdout: %s\n", uv_strerror(req->result));
        uv_fs_close(ctx->loop, &ctx->close_req, ctx->file_fd, close_cb);
    }
}

static void read_cb(uv_fs_t *req) {
    struct uvcat_context *ctx = req->data;
    assert(req == &ctx->read_req);
    
    if (req->result > 0) {
        ctx->bytes_read += req->result;
        ctx->buffers[ctx->current_buffer].len = req->result;
        
        // 写入到标准输出
        uv_fs_write(ctx->loop, &ctx->write_req, STDOUT_FILENO, 
                   &ctx->buffers[ctx->current_buffer], 1, -1, write_cb);
    } else if (req->result == 0) {
        // EOF - 关闭文件
        uv_fs_close(ctx->loop, &ctx->close_req, ctx->file_fd, close_cb);
    } else {
        fprintf(stderr, "Error reading file: %s\n", uv_strerror(req->result));
        uv_fs_close(ctx->loop, &ctx->close_req, ctx->file_fd, close_cb);
    }
}

static void open_cb(uv_fs_t *req) {
    struct uvcat_context *ctx = req->data;
    assert(req == &ctx->open_req);
    
    if (req->result >= 0) {
        ctx->file_fd = req->result;
        fprintf(stderr, "File opened successfully, starting to read...\n");
        
        // 开始读取
        uv_fs_read(ctx->loop, &ctx->read_req, ctx->file_fd, 
                   &ctx->buffers[ctx->current_buffer], 1, -1, read_cb);
    } else {
        fprintf(stderr, "Error opening file: %s\n", uv_strerror(req->result));
        uv_stop(ctx->loop);
    }
}

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <file>\n", argv[0]);
        return 1;
    }
    
    struct uvcat_context ctx;
    g_ctx = &ctx;
    
    // 设置信号处理器
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    uvcat_context_init(&ctx, uv_default_loop());
    
    // 打开文件
    uv_fs_open(ctx.loop, &ctx.open_req, argv[1], O_RDONLY, 0, open_cb);
    
    // 运行事件循环
    int result = uv_run(ctx.loop, UV_RUN_DEFAULT);
    
    // 清理资源
    uvcat_context_cleanup(&ctx);
    uv_loop_close(ctx.loop);
    
    g_ctx = NULL;
    
    return result == 0 ? 0 : 1;
}